<template>
  <div
    class="dropdown"
    @mouseenter="onMouseEnter"
    @mouseleave="onMouseLeave"
    ref="dropdownRef"
  >
    <div class="reference-wrapper" ref="referenceRef">
      <slot name="reference" />
    </div>
    <transition>
      <div
        ref="containerRef"
        class="container"
        :class="systemStore.themeClass"
        v-show="isShow"
        :style="containerStyle"
      >
        <slot />
      </div>
    </transition>
  </div>
</template>

<script>
const PROP_TOP_LEFT = 'top-left'
const PROP_TOP_RIGHT = 'top-right'
const PROP_BOTTOM_LEFT = 'bottom-left'
const PROP_BOTTOM_RIGHT = 'bottom-right'

const placementEnum = [
  PROP_TOP_LEFT,
  PROP_TOP_RIGHT,
  PROP_BOTTOM_LEFT,
  PROP_BOTTOM_RIGHT
]
</script>

<script setup>
import { ref, watch, nextTick } from 'vue'
import { useSystemStore } from '@/store/system'

const props = defineProps({
  placement: {
    type: String,
    default: 'bottom-left',
    validator(placement) {
      if (!placementEnum.includes(placement)) {
        throw new Error(
          `您指定的placement必须是${placementEnum.join('、')}中的一个`
        )
      }
      return placement
    }
  }
})

const systemStore = useSystemStore()
const isShow = ref(false)

let lock
const onMouseEnter = () => {
  if (lock) {
    clearTimeout(lock)
  }
  isShow.value = true
}
const onMouseLeave = () => {
  lock = setTimeout(() => {
    isShow.value = false
  }, 300)
}

const dropdownRef = ref(null)
const containerRef = ref(null)

const useElementSize = (el) => {
  if (!el) return
  return {
    width: el.offsetWidth,
    height: el.offsetHeight
  }
}

// 弹层位置
const containerStyle = ref({
  top: null,
  left: null
})

watch(isShow, async (val) => {
  if (!val) return
  await nextTick()
  const containerEl = useElementSize(containerRef.value)
  const dropdownEl = useElementSize(dropdownRef.value)
  switch (props.placement) {
    // 左上
    case PROP_TOP_LEFT:
      containerStyle.value.top = `0px`
      containerStyle.value.left = `${-containerEl.width}px`
      break
    // 左下
    case PROP_BOTTOM_LEFT:
      containerStyle.value.left = `${-containerEl.width}px`
      containerStyle.value.top = `${dropdownEl.height}px`
      break
    // 右上
    case PROP_TOP_RIGHT:
      containerStyle.value.left = `${dropdownEl.width}px`
      containerStyle.value.top = `0px`
      break
    // 右下
    case PROP_BOTTOM_RIGHT:
      containerStyle.value.left = `${dropdownEl.width}px`
      containerStyle.value.top = `${dropdownEl.height}px`
      break
  }
})
</script>

<style lang="scss" scoped>
.dropdown {
  position: relative;
  .container {
    position: absolute;
    z-index: 99;
    background-color: #fff;
    padding: 0.1rem;
    width: 140px;
    border-radius: 10px;
    box-shadow: 0px 0px 8px 2px #ddd4d4;
    font-size: 0.14rem;
  }
}
.v-enter-active,
.v-leave-active {
  transition: all 0.3s ease;
}

.v-enter-from,
.v-leave-to {
  transform: translate3d(0, 50px, 0);
  opacity: 0;
}
</style>
